/*******************************************************************************
*                                    ZLG
*                         ----------------------------
*                         innovating embedded platform
*
* Copyright (c) 2001-present Guangzhou ZHIYUAN Electronics Co., Ltd.
* All rights reserved.
*
* Contact information:
* web site:    https://www.zlg.cn
*******************************************************************************/
#ifndef __HPM6E00_GPTIMER_H__
#define __HPM6E00_GPTIMER_H__

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus*/
#include "common/hpm_errno.h"
#include "common/hpm_common.h"
#include "core/include/hpm6e00_regs_gptimer.h"

/* \brief 通用定时器一个通道支持的输出比较数*/
#define GPTMR_CH_CMP_COUNT (2U)

/* \brief 通用定时器工作模式*/
typedef enum gptmr_work_mode {
    gptmr_work_mode_no_capture              = 0,
    gptmr_work_mode_capture_at_rising_edge  = 1,
    gptmr_work_mode_capture_at_falling_edge = 2,
    gptmr_work_mode_capture_at_both_edge    = 3,
    gptmr_work_mode_measure_width           = 4,
} gptmr_work_mode_t;

/* \brief 通用定时器 DMA 请求事件*/
typedef enum gptmr_dma_request_event {
   gptmr_dma_request_on_reload = 0,
   gptmr_dma_request_on_input_signal_toggle = 1,
   gptmr_dma_request_on_cmp0 = 2,
   gptmr_dma_request_on_cmp1 = 3,
   gptmr_dma_request_disabled = 0xFF,
} gptmr_dma_request_event_t;

/* \brief 通用定时器 SYNCI 边沿有效选择*/
typedef enum gptmr_synci_edge {
    gptmr_synci_edge_none    = 0,
    gptmr_synci_edge_falling = GPTMR_CHANNEL_CR_SYNCIFEN_MASK,
    gptmr_synci_edge_rising  = GPTMR_CHANNEL_CR_SYNCIREN_MASK,
    gptmr_synci_edge_both    = gptmr_synci_edge_falling | gptmr_synci_edge_rising,
} gptmr_synci_edge_t;

/* \brief 通用定时器通道重载状态掩码*/
#define GPTMR_CH_RLD_STAT_MASK(ch)        (1 << (ch * 4))

/* \brief DMA 请求选择设置*/
#define GPTMR_CHANNEL_CR_DMASEL_SET(x)    (((uint32_t)(x) << GPTMR_CHANNEL_CR_DMASEL_POS) & GPTMR_CHANNEL_CR_DMASEL_MASK)
/* \brief 获取 DMA 请求选择*/
#define GPTMR_CHANNEL_CR_DMASEL_GET(x)    (((uint32_t)READ_REG32(x) & GPTMR_CHANNEL_CR_DMASEL_MASK) >> GPTMR_CHANNEL_CR_DMASEL_POS)

/* \brief 设置输入捕获模式使能位*/
#define GPTMR_CHANNEL_CR_CAPMODE_SET(x)   (((uint32_t)(x) << GPTMR_CHANNEL_CR_CAPMODE_POS) & GPTMR_CHANNEL_CR_CAPMODE_MASK)
/* \brief 获取输入捕获模式使能位*/
#define GPTMR_CHANNEL_CR_CAPMODE_GET(x)   (((uint32_t)READ_REG32(x) & GPTMR_CHANNEL_CR_CAPMODE_MASK) >> GPTMR_CHANNEL_CR_CAPMODE_POS)

/* \brief 设置调试停止模式使能位*/
#define GPTMR_CHANNEL_CR_DBGPAUSE_SET(x)  (((uint32_t)(x) << GPTMR_CHANNEL_CR_DBGPAUSE_POS) & GPTMR_CHANNEL_CR_DBGPAUSE_MASK)
/* \brief 获取调试停止模式使能位*/
#define GPTMR_CHANNEL_CR_DBGPAUSE_GET(x)  (((uint32_t)READ_REG32(x) & GPTMR_CHANNEL_CR_DBGPAUSE_MASK) >> GPTMR_CHANNEL_CR_DBGPAUSE_POS)

/* \brief 设置软件同步使能位*/
#define GPTMR_CHANNEL_CR_SWSYNCIEN_SET(x) (((uint32_t)(x) << GPTMR_CHANNEL_CR_SWSYNCIEN_POS) & GPTMR_CHANNEL_CR_SWSYNCIEN_MASK)
/* \brief 获取软件同步使能位*/
#define GPTMR_CHANNEL_CR_SWSYNCIEN_GET(x) (((uint32_t)READ_REG32(x) & GPTMR_CHANNEL_CR_SWSYNCIEN_MASK) >> GPTMR_CHANNEL_CR_SWSYNCIEN_POS)

/* \brief 设置通道输出比较功能初始化*/
#define GPTMR_CHANNEL_CR_CMPINIT_SET(x)   (((uint32_t)(x) << GPTMR_CHANNEL_CR_CMPINIT_POS) & GPTMR_CHANNEL_CR_CMPINIT_MASK)
/* \brief 获取通道输出比较功能初始化*/
#define GPTMR_CHANNEL_CR_CMPINIT_GET(x)   (((uint32_t)READ_REG32(x) & GPTMR_CHANNEL_CR_CMPINIT_MASK) >> GPTMR_CHANNEL_CR_CMPINIT_POS)

#define GPTMR_CHANNEL_CR_SYNCFLW_SET(x)   (((uint32_t)(x) << GPTMR_CHANNEL_CR_SYNCFLW_POS) & GPTMR_CHANNEL_CR_SYNCFLW_MASK)
#define GPTMR_CHANNEL_CR_SYNCFLW_GET(x)   (((uint32_t)READ_REG32(x) & GPTMR_CHANNEL_CR_SYNCFLW_MASK) >> GPTMR_CHANNEL_CR_SYNCFLW_POS)

/* \brief 设置通道输出比较功能使能位*/
#define GPTMR_CHANNEL_CR_CMPEN_SET(x)     (((uint32_t)(x) << GPTMR_CHANNEL_CR_CMPEN_POS) & GPTMR_CHANNEL_CR_CMPEN_MASK)
/* \brief 获取通道输出比较功能使能位*/
#define GPTMR_CHANNEL_CR_CMPEN_GET(x)     (((uint32_t)READ_REG32(x) & GPTMR_CHANNEL_CR_CMPEN_MASK) >> GPTMR_CHANNEL_CR_CMPEN_POS)

/* \brief 计数器使能设置*/
#define GPTMR_CHANNEL_CR_CEN_SET(x)       (((uint32_t)(x) << GPTMR_CHANNEL_CR_CEN_POS) & GPTMR_CHANNEL_CR_CEN_MASK)
/* \brief 获取计数器使能位*/
#define GPTMR_CHANNEL_CR_CEN_GET(x)       (((uint32_t)READ_REG32(x) & GPTMR_CHANNEL_CR_CEN_MASK) >> GPTMR_CHANNEL_CR_CEN_POS)

/* \brief 比较值设置*/
#define GPTMR_CMP_CMP_SET(x)              (((uint32_t)(x) << GPTMR_CMP_CMP_POS) & GPTMR_CMP_CMP_MASK)
/* \brief 获取比较值*/
#define GPTMR_CMP_CMP_GET(x)              (((uint32_t)READ_REG32(x) & GPTMR_CMP_CMP_MASK) >> GPTMR_CMP_CMP_POS)

/* \brief 重载值设置*/
#define GPTMR_CHANNEL_RLD_RLD_SET(x)      (((uint32_t)(x) << GPTMR_CHANNEL_RLD_RLD_POS) & GPTMR_CHANNEL_RLD_RLD_MASK)
/* \brief 获取重载值*/
#define GPTMR_CHANNEL_RLD_RLD_GET(x)      (((uint32_t)READ_REG32(x) & GPTMR_CHANNEL_RLD_RLD_MASK) >> GPTMR_CHANNEL_RLD_RLD_POS)

/* \brief 设置通道中断掩码*/
#define GPTMR_CH_CMP_IRQ_MASK(ch, cmp)      (1 << (ch * 4 + 2 + cmp))

/* \brief 通用定时器通道配置结构体*/
struct gptmr_ch_cfg {
    gptmr_work_mode_t         mode;                                /* 工作模式*/
    gptmr_dma_request_event_t dma_request_event;                   /* DMA 请求事件*/
    gptmr_synci_edge_t        synci_edge;
    uint32_t                  cmp[GPTMR_CH_CMP_COUNT];             /* 比较通道*/
    uint32_t                  reload;                              /* 重载值*/
    bool_t                    cmp_initial_polarity_high;
    bool_t                    enable_cmp_output;                   /* 是否使能输出比较*/
    bool_t                    enable_sync_follow_previous_channel;
    bool_t                    enable_software_sync;                /* 是否使能软件同步*/
    bool_t                    debug_mode;                          /* 是否在调试模式*/
};

/**
 * \brief 通用定时器获取通道默认配置
 *
 * \param[in] p_gptmr_reg 具体的定时器寄存器
 * \param[in] p_cfg       存储配置的缓存
 */
void gptmr_ch_default_cfg_get(hpm_gptmr_reg_t     *p_gptmr_reg,
                              struct gptmr_ch_cfg *p_cfg);
/**
 * \brief 通用定时器通道初始化
 *
 * \param[in] p_gptmr_reg 具体的定时器寄存器
 * \param[in] ch_idx      定时器通道索引
 * \param[in] p_cfg       具体配置
 * \param[in] is_enable   是否使能
 *
 * \retval 成功返回 0
 */
int gptmr_ch_init(hpm_gptmr_reg_t     *p_gptmr_reg,
                  uint8_t              ch_idx,
                  struct gptmr_ch_cfg *p_cfg,
                  bool_t               is_enable);
/**
 * \brief 通用定时器通道反初始化
 *
 * \param[in] p_gptmr_reg 具体的定时器寄存器
 * \param[in] ch_idx      定时器通道索引
 *
 * \retval 成功返回 0
 */
int gptmr_ch_deinit(hpm_gptmr_reg_t *p_gptmr_reg,
                    uint8_t          ch_idx);
/**
 * \brief 检查通用定时器状态是否匹配状态掩码
 *
 * \param[in] p_gptmr_reg 具体的定时器寄存器
 * \param[in] status_mask 状态掩码
 *
 * \retval 匹配返回 0
 */
int gptmr_status_chk(hpm_gptmr_reg_t *p_gptmr_reg, uint32_t status_mask);
/**
 * \brief 清除通用定时器具体的状态
 *
 * \param[in] p_gptmr_reg 具体的定时器寄存器
 * \param[in] status_mask 要清除的状态
 *
 * \retval 成功返回 0
 */
int gptmr_status_clr(hpm_gptmr_reg_t *p_gptmr_reg, uint32_t status_mask);
/**
 * \brief 通用定时器使能中断
 *
 * \param[in] p_gptmr_reg 具体的定时器寄存器
 * \param[in] irq_mask    要使能的中断
 *
 * \retval 成功返回 0
 */
int gptmr_irq_enable(hpm_gptmr_reg_t *p_gptmr_reg, uint32_t irq_mask);
/**
 * \brief 通用定时器禁能中断
 *
 * \param[in] p_gptmr_reg 具体的定时器寄存器
 * \param[in] irq_mask    要禁能的中断
 *
 * \retval 成功返回 0
 */
int gptmr_irq_disable(hpm_gptmr_reg_t *p_gptmr_reg, uint32_t irq_mask);
/**
 * \brief 配置通道重载值
 *
 * \param[in] p_gptmr_reg 具体的定时器寄存器
 * \param[in] ch_idx      定时器通道索引
 * \param[in] reload      重载值
 *
 * \retval 成功返回 0
 */
int gptmr_ch_reload_cfg(hpm_gptmr_reg_t *p_gptmr_reg,
                        uint8_t          ch_idx,
                        uint32_t         reload);
/**
 * \brief 计数器启动
 *
 * \param[in] p_gptmr_reg 具体的定时器寄存器
 * \param[in] ch_idx      定时器通道索引
 *
 * \retval 成功返回 0
 */
int gptmr_counter_start(hpm_gptmr_reg_t *p_gptmr_reg, uint8_t ch_idx);
/**
 * \brief 计数器停止
 *
 * \param[in] p_gptmr_reg 具体的定时器寄存器
 * \param[in] ch_idx      定时器通道索引
 *
 * \retval 成功返回 0
 */
int gptmr_counter_stop(hpm_gptmr_reg_t *p_gptmr_reg, uint8_t ch_idx);
/**
 * \brief 计数器值获取
 *
 * \param[in] p_gptmr_reg 具体的定时器寄存器
 * \param[in] ch_idx      定时器通道索引
 *
 * \retval 成功返回 计数器计数值
 */
uint32_t gptmr_counter_get(hpm_gptmr_reg_t *p_gptmr_reg, uint8_t ch_idx);
#ifdef __cplusplus
}
#endif  /* __cplusplus  */
#endif



